//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "BindingInfoCathFASTAProfile.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHTEXT 500000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfoCathFASTAProfile::BindingInfoCathFASTAProfile() {
  
  this->ligand        = new String ();
  this->bindingRegion = new BindingInfo ();
  this->cathProfile   = new CathFASTAProfile (); 
  this->toString      = new String ();
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfoCathFASTAProfile::BindingInfoCathFASTAProfile(const BindingInfoCathFASTAProfile& bindingInfoCathFASTAProfile) {
  
  this->ligand        = new String (bindingInfoCathFASTAProfile.ligand);
  this->bindingRegion = new BindingInfo (bindingInfoCathFASTAProfile.bindingRegion);
  this->cathProfile   = new CathFASTAProfile (bindingInfoCathFASTAProfile.cathProfile); 
  this->toString      = new String (bindingInfoCathFASTAProfile.toString);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfoCathFASTAProfile::BindingInfoCathFASTAProfile(const BindingInfoCathFASTAProfile* bindingInfoCathFASTAProfile) {
  
  this->ligand        = new String (bindingInfoCathFASTAProfile->ligand);
  this->bindingRegion = new BindingInfo (bindingInfoCathFASTAProfile->bindingRegion);
  this->cathProfile   = new CathFASTAProfile (bindingInfoCathFASTAProfile->cathProfile); 
  this->toString      = new String (bindingInfoCathFASTAProfile->toString);
    
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfoCathFASTAProfile::~BindingInfoCathFASTAProfile() {
  
  if (this->ligand)        delete this->ligand;
  if (this->bindingRegion) delete this->bindingRegion;
  if (this->cathProfile)   delete this->cathProfile; 
  if (this->toString)      delete this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void BindingInfoCathFASTAProfile::Ligand (String* ligand) {
  
  if (ligand) this->ligand->In(ligand);
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void BindingInfoCathFASTAProfile::BindingRegion (BindingInfo* bindingRegion) {
  
  if (bindingRegion) *(this->bindingRegion) = *bindingRegion;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void BindingInfoCathFASTAProfile::CathProfile (CathFASTAProfile* cathProfile) {
  
  if (cathProfile) *(this->cathProfile) = *cathProfile;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::Ligand (void) {
  
  return this->ligand;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfo* BindingInfoCathFASTAProfile::BindingRegion (void) {
  
  return this->bindingRegion;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
CathFASTAProfile* BindingInfoCathFASTAProfile::CathProfile (void) {
  
  return this->cathProfile;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfile (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              sequence;
    String              secondaryStructureP;
    String              secondaryStructureC;
    String              residuesClassChemical;
    String              residuesClassPhysical;
    String              residuesMT;

    sequence.In("<");
    secondaryStructureP.In("+");
    secondaryStructureC.In("-");
    residuesClassChemical.In(":");
    residuesClassPhysical.In(";");
    residuesMT.In("!");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) {
        sequence.Add("-");
        secondaryStructureP.Add("-");
        secondaryStructureC.Add("-");
        residuesClassChemical.Add("-");
        residuesClassPhysical.Add("-");
        residuesMT.Add("-");
      }
      
      sequence.Add(this->cathProfile->Sequence()->Out()[currentPosition - positionStart]);
      secondaryStructureP.Add(this->cathProfile->SecondaryStructureP()->Out()[currentPosition - positionStart]);
      secondaryStructureC.Add(this->cathProfile->SecondaryStructureC()->Out()[currentPosition - positionStart]);
      residuesClassChemical.Add(this->cathProfile->ResiduesClassChemical()->Out()[currentPosition - positionStart]);
      residuesClassPhysical.Add(this->cathProfile->ResiduesClassPhysical()->Out()[currentPosition - positionStart]);
      residuesMT.Add(this->cathProfile->ResiduesMT()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(sequence);              this->toString->Add("\n");
    this->toString->Add(secondaryStructureP);   this->toString->Add("\n");
    this->toString->Add(secondaryStructureC);   this->toString->Add("\n");
    this->toString->Add(residuesClassChemical); this->toString->Add("\n");
    this->toString->Add(residuesClassPhysical); this->toString->Add("\n");
    this->toString->Add(residuesMT);            
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSeq (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              sequence;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        sequence.Add("-");
      
      sequence.Add(this->cathProfile->Sequence()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(sequence); 
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSS (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              secondaryStructureP;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        secondaryStructureP.Add("-");
      
      secondaryStructureP.Add(this->cathProfile->SecondaryStructureP()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(secondaryStructureP);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSSConf (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              secondaryStructureC;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        secondaryStructureC.Add("-");
      
      secondaryStructureC.Add(this->cathProfile->SecondaryStructureC()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(secondaryStructureC);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileCH (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesClassChemical;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        residuesClassChemical.Add("-");
      
      residuesClassChemical.Add(this->cathProfile->ResiduesClassChemical()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(residuesClassChemical);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfilePH (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesClassPhysical;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        residuesClassPhysical.Add("-");
      
      residuesClassPhysical.Add(this->cathProfile->ResiduesClassPhysical()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(residuesClassPhysical);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileMT (void) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesMT;

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue  = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      if ((previousResidue)  && ((previousPosition + 1) != currentPosition)) 
        residuesMT.Add("-");
      
      residuesMT.Add(this->cathProfile->ResiduesMT()->Out()[currentPosition - positionStart]);
      
      previousResidue  = currentResidue;
      previousPosition = currentPosition;
      
    }
    
    this->toString->Add(residuesMT);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileExtended (int extension = 0) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              sequence;
    String              secondaryStructureP;
    String              secondaryStructureC;
    String              residuesClassChemical;
    String              residuesClassPhysical;
    String              residuesMT;

    sequence.In("<");
    secondaryStructureP.In("+");
    secondaryStructureC.In("-");
    residuesClassChemical.In(":");
    residuesClassPhysical.In(";");
    residuesMT.In("!");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) {
        sequence.Add("-");
        secondaryStructureP.Add("-");
        secondaryStructureC.Add("-");
        residuesClassChemical.Add("-");
        residuesClassPhysical.Add("-");
        residuesMT.Add("-");
      }
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        
        sequence.Add(this->cathProfile->Sequence()->Out()[i - positionStart]);
        secondaryStructureP.Add(this->cathProfile->SecondaryStructureP()->Out()[i - positionStart]);
        secondaryStructureC.Add(this->cathProfile->SecondaryStructureC()->Out()[i - positionStart]);
        residuesClassChemical.Add(this->cathProfile->ResiduesClassChemical()->Out()[i - positionStart]);
        residuesClassPhysical.Add(this->cathProfile->ResiduesClassPhysical()->Out()[i - positionStart]);
        residuesMT.Add(this->cathProfile->ResiduesMT()->Out()[i - positionStart]);

        previousPosition = i;
        
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(sequence);              this->toString->Add("\n");
    this->toString->Add(secondaryStructureP);   this->toString->Add("\n");
    this->toString->Add(secondaryStructureC);   this->toString->Add("\n");
    this->toString->Add(residuesClassChemical); this->toString->Add("\n");
    this->toString->Add(residuesClassPhysical); this->toString->Add("\n");
    this->toString->Add(residuesMT);            
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSeqExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              sequence;

    sequence.In("<");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        sequence.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        sequence.Add(this->cathProfile->Sequence()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(sequence);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSSExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              secondaryStructureP;

    secondaryStructureP.In("+");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        secondaryStructureP.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        secondaryStructureP.Add(this->cathProfile->SecondaryStructureP()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(secondaryStructureP);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileSSConfExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              secondaryStructureC;

    secondaryStructureC.In("-");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        secondaryStructureC.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        secondaryStructureC.Add(this->cathProfile->SecondaryStructureC()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(secondaryStructureC);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileCHExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesClassChemical;

    residuesClassChemical.In(":");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        residuesClassChemical.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        residuesClassChemical.Add(this->cathProfile->ResiduesClassChemical()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(residuesClassChemical);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfilePHExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesClassPhysical;

    residuesClassPhysical.In(";");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        residuesClassPhysical.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        residuesClassPhysical.Add(this->cathProfile->ResiduesClassPhysical()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(residuesClassPhysical);
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* BindingInfoCathFASTAProfile::ToStringBindingInfoInCathProfileMTExtended (int extension) {
  
  this->toString->In("");
  
  if (!this->bindingRegion || !this->cathProfile || !this->toString)
    return this->toString;
  
  bool start = true;
  
  this->bindingRegion->NearResiduesByLigand()->SetInitial();
  while (this->bindingRegion->NearResiduesByLigand()->SetNext()) {

    LigandNearResidues* currentLigandNearResidues = this->bindingRegion->NearResiduesByLigand()->GetCurrent();
    int                 segment                   = (this->bindingRegion->Segments()->Length())?0:-1;

    if (segment == -1) { this->toString->In(""); return this->toString; }
    
    if (start) start = false; 
    else       this->toString->Add("\n"); 
    
    this->toString->Add(this->cathProfile->ToStringHeader());
    this->toString->Add(" @ ");
    this->toString->Add(currentLigandNearResidues->LigandName());
    this->toString->Add("-");
    this->toString->Add(currentLigandNearResidues->LigandNumber());
    this->toString->Add("\n");

    int                 positionStart             = this->bindingRegion->Segments()->Get(segment)->RangeStart();
    int                 positionEnd               = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
    
    String              residuesMT;

    residuesMT.In("!");

    String*             previousResidue           = NULL;
    int                 previousPosition          = -1;
    
    currentLigandNearResidues->NearResidues()->SetInitial();
    while (currentLigandNearResidues->NearResidues()->SetNext()) {
      
      String* currentResidue     = currentLigandNearResidues->NearResidues()->GetCurrent();
      int     currentPosition    = atoi(currentResidue->Out() + 3);
      
      if (currentPosition > positionEnd) {
        
        segment++;
        
        if (segment >= this->bindingRegion->Segments()->Length()) 
          break;
        
        positionStart   = this->bindingRegion->Segments()->Get(segment)->RangeStart();
        positionEnd     = this->bindingRegion->Segments()->Get(segment)->RangeEnd();
        
      }
      
      int startRangePosition = ((currentPosition - extension) < positionStart)?positionStart:(currentPosition - extension);
      int endRangePosition   = ((currentPosition + extension) > positionEnd)?positionEnd:(currentPosition + extension);
      
      if ((previousResidue)  && ((previousPosition + 1) != startRangePosition) && ((previousPosition) < startRangePosition)) 
        residuesMT.Add("-");
      
      for (int i = (startRangePosition <= previousPosition)?(previousPosition + 1):startRangePosition; i <= endRangePosition; i++) {
        residuesMT.Add(this->cathProfile->ResiduesMT()->Out()[i - positionStart]);
        previousPosition = i;
      }
      
      previousResidue  = currentResidue;
      
    }
    
    this->toString->Add(residuesMT);            
    
  }
  
  return this->toString;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
BindingInfoCathFASTAProfile BindingInfoCathFASTAProfile::operator= (const BindingInfoCathFASTAProfile& bindingInfoCathFASTAProfile) {
  
  this->ligand->In(bindingInfoCathFASTAProfile.ligand);
  
  *(this->bindingRegion) = *(bindingInfoCathFASTAProfile.bindingRegion);
  *(this->cathProfile)   = *(bindingInfoCathFASTAProfile.cathProfile); 
  
  this->toString->In(bindingInfoCathFASTAProfile.toString);
  
  return *this;
  
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
